home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / TxtPlayer / vcdplyer.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  21.4 KB  |  945 lines

  1. //------------------------------------------------------------------------------
  2. // File: vcdplyer.cpp
  3. //
  4. // Desc: DirectShow sample code - VMR-enabled player app with text
  5. //
  6. // Copyright (c) 1994 - 2001, Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9. #include <streams.h>
  10. #include <mmreg.h>
  11. #include <commctrl.h>
  12. #include <atlbase.h>
  13.  
  14. #include "project.h"
  15. #include "mpgcodec.h"
  16.  
  17. #include <stdarg.h>
  18. #include <stdio.h>
  19.  
  20. extern int FrameStepCount;
  21.  
  22.  
  23. /******************************Public*Routine******************************\
  24. * CMpegMovie
  25. *
  26. * Constructors and destructors
  27. *
  28. \**************************************************************************/
  29. CMpegMovie::CMpegMovie(HWND hwndApplication)
  30.     : CUnknown(NAME("Allocator Presenter"), NULL),
  31.       m_hwndApp(hwndApplication),
  32.       m_MediaEvent(NULL),
  33.       m_Mode(MOVIE_NOTOPENED),
  34.       m_Fg(NULL),
  35.       m_Gb(NULL),
  36.       m_Mc(NULL),
  37.       m_Ms(NULL),
  38.       m_Me(NULL),
  39.       m_Wc(NULL),
  40.       m_SAN(NULL),
  41.       m_bRndLess(TRUE),
  42.       pMpegAudioDecoder(NULL),
  43.       pVideoRenderer(NULL),
  44.       m_TimeFormat(TIME_FORMAT_MEDIA_TIME),
  45.       m_hFont(NULL),
  46.       m_cxFont(0), m_cxFontImg(0),
  47.       m_cyFont(0), m_cyFontImg(0),
  48.       m_lpDDSFontCache(NULL)
  49. {
  50.     m_hMonitor = NULL;
  51.     m_lpDDObj = NULL;
  52.     m_lpPriSurf = NULL;
  53.     m_lpBackBuffer = NULL;
  54.     m_lpDDTexture = NULL;
  55.  
  56.     AddRef();
  57. }
  58. CMpegMovie::~CMpegMovie()
  59. {
  60. }
  61.  
  62.  
  63. static HRESULT SetRenderingMode( IBaseFilter* pBaseFilter, VMRMode mode )
  64. {
  65.     // Test VMRConfig, VMRMonitorConfig
  66.     IVMRFilterConfig* pConfig;
  67.     HRESULT hr = pBaseFilter->QueryInterface(IID_IVMRFilterConfig, (LPVOID *)&pConfig);
  68.     if(SUCCEEDED(hr))
  69.     {
  70.         pConfig->SetRenderingMode(mode);
  71.         pConfig->SetRenderingPrefs(RenderPrefs_AllowOverlays);
  72.         pConfig->Release();
  73.     }
  74.     return hr;
  75. }
  76.  
  77. /******************************Public*Routine******************************\
  78. * AddVideoMixingRendererToFG
  79. *
  80. \**************************************************************************/
  81. HRESULT
  82. CMpegMovie::AddVideoMixingRendererToFG()
  83. {
  84.     IBaseFilter* pBF = NULL;
  85.     HRESULT hRes = CoCreateInstance(CLSID_VideoMixingRenderer,
  86.         NULL,
  87.         CLSCTX_INPROC,
  88.         IID_IBaseFilter,
  89.         (LPVOID *)&pBF);
  90.  
  91.     if(SUCCEEDED(hRes))
  92.     {
  93.         hRes = m_Fg->AddFilter(pBF, L"Video Mixing Renderer");
  94.  
  95.         if(SUCCEEDED(hRes))
  96.         {
  97.             if(m_bRndLess)
  98.             {
  99.                 hRes = SetRenderingMode(pBF, VMRMode_Renderless);
  100.  
  101.                 if(SUCCEEDED(hRes))
  102.                 {
  103.                     hRes = pBF->QueryInterface(IID_IVMRSurfaceAllocatorNotify,
  104.                         (LPVOID *)&m_SAN);
  105.                 }
  106.  
  107.                 if(SUCCEEDED(hRes))
  108.                 {
  109.                     hRes = m_SAN->AdviseSurfaceAllocator(0, this);
  110.                 }
  111.  
  112.                 if(SUCCEEDED(hRes))
  113.                 {
  114.                     hRes = m_SAN->SetDDrawDevice(m_lpDDObj, m_hMonitor);
  115.                 }
  116.             }
  117.             else
  118.             {
  119.                 hRes = SetRenderingMode(pBF, VMRMode_Windowless);
  120.                 if(SUCCEEDED(hRes))
  121.                 {
  122.                     hRes = pBF->QueryInterface(IID_IVMRWindowlessControl, (LPVOID *)&m_Wc);
  123.                 }
  124.  
  125.                 if(SUCCEEDED(hRes))
  126.                 {
  127.                     m_Wc->SetVideoClippingWindow(m_hwndApp);
  128.                 }
  129.                 else
  130.                 {
  131.                     if(m_Wc)
  132.                     {
  133.                         m_Wc->Release();
  134.                         m_Wc = NULL;
  135.                     }
  136.                 }
  137.             }
  138.         }
  139.     }
  140.  
  141.     if(pBF)
  142.     {
  143.         pBF->Release();
  144.     }
  145.  
  146.     if(FAILED(hRes))
  147.     {
  148.         if(m_SAN)
  149.         {
  150.             m_SAN->Release();
  151.             m_SAN = NULL;
  152.         }
  153.     }
  154.  
  155.     return hRes;
  156. }
  157.  
  158. /******************************Public*Routine******************************\
  159. * OpenMovie
  160. *
  161. \**************************************************************************/
  162. HRESULT
  163. CMpegMovie::OpenMovie(
  164.     TCHAR *lpFileName
  165.     )
  166. {
  167.     USES_CONVERSION;
  168.     IUnknown        *pUnk;
  169.     HRESULT         hres;
  170.     WCHAR           FileName[MAX_PATH];
  171.  
  172.     wcscpy(FileName, T2W(lpFileName));
  173.  
  174.     hres = CoInitialize(NULL);
  175.     if(hres == S_FALSE)
  176.     {
  177.         CoUninitialize();
  178.     }
  179.  
  180.     Initialize3DEnvironment(m_hwndApp);
  181.  
  182.     hres = CoCreateInstance(
  183.         CLSID_FilterGraph,
  184.         NULL,
  185.         CLSCTX_INPROC,
  186.         IID_IUnknown,
  187.         (LPVOID *)&pUnk);
  188.  
  189.     if(SUCCEEDED(hres))
  190.     {
  191.         m_Mode = MOVIE_OPENED;
  192.         hres = pUnk->QueryInterface(IID_IFilterGraph, (LPVOID *)&m_Fg);
  193.         if(FAILED(hres))
  194.         {
  195.             pUnk->Release();
  196.             return hres;
  197.         }
  198.  
  199.         hres = AddVideoMixingRendererToFG();
  200.         if(FAILED(hres))
  201.         {
  202.             m_Fg->Release(); m_Fg = NULL;
  203.             return hres;
  204.         }
  205.  
  206.         hres = pUnk->QueryInterface(IID_IGraphBuilder, (LPVOID *)&m_Gb);
  207.         if(FAILED(hres))
  208.         {
  209.             pUnk->Release();
  210.             m_Fg->Release(); m_Fg = NULL;
  211.             m_Wc->Release(); m_Wc = NULL;
  212.             return hres;
  213.         }
  214.  
  215.         hres = m_Gb->RenderFile(FileName, NULL);
  216.         if(FAILED(hres))
  217.         {
  218.             pUnk->Release();
  219.             m_Fg->Release(); m_Fg = NULL;
  220.             if(m_Wc)
  221.                 m_Wc->Release(); m_Wc = NULL;
  222.             m_Gb->Release(); m_Gb = NULL;
  223.             return hres;
  224.         }
  225.  
  226.         hres = pUnk->QueryInterface(IID_IMediaControl, (LPVOID *)&m_Mc);
  227.         if(FAILED(hres))
  228.         {
  229.             pUnk->Release();
  230.             m_Fg->Release(); m_Fg = NULL;
  231.             m_Wc->Release(); m_Wc = NULL;
  232.             m_Gb->Release(); m_Gb = NULL;
  233.             return hres;
  234.         }
  235.  
  236.         //
  237.         // Not being able to get the IMediaEvent interface does not
  238.         // necessarly mean that we can't play the graph.
  239.         //
  240.         pUnk->QueryInterface(IID_IMediaEvent, (LPVOID *)&m_Me);
  241.         pUnk->QueryInterface(IID_IMediaSeeking, (LPVOID *)&m_Ms);
  242.  
  243.         GetMovieEventHandle();
  244.         GetPerformanceInterfaces();
  245.  
  246.         pUnk->Release();
  247.         return S_OK;
  248.  
  249.     }
  250.     else
  251.     {
  252.         m_Fg = NULL;
  253.     }
  254.  
  255.     return hres;
  256. }
  257.  
  258.  
  259. /******************************Public*Routine******************************\
  260. * CloseMovie
  261. *
  262. \**************************************************************************/
  263. DWORD
  264. CMpegMovie::CloseMovie(
  265.     )
  266. {
  267.     m_Mode = MOVIE_NOTOPENED;
  268.  
  269.     if(m_Mc)
  270.     {
  271.         if(pMpegAudioDecoder)
  272.         {
  273.             pMpegAudioDecoder->Release();
  274.             pMpegAudioDecoder = NULL;
  275.         }
  276.  
  277.         if(pVideoRenderer)
  278.         {
  279.             pVideoRenderer->Release();
  280.             pVideoRenderer = NULL;
  281.         }
  282.  
  283.         if(m_Me)
  284.         {
  285.             m_MediaEvent = NULL;
  286.             m_Me->Release();
  287.             m_Me = NULL;
  288.         }
  289.  
  290.         if(m_Ms)
  291.         {
  292.             m_Ms->Release();
  293.             m_Ms = NULL;
  294.         }
  295.  
  296.         if(m_Wc)
  297.         {
  298.             m_Wc->Release();
  299.             m_Wc = NULL;
  300.         }
  301.  
  302.         m_Mc->Release();
  303.         m_Mc = NULL;
  304.  
  305.         if(m_SAN)
  306.         {
  307.             m_SAN->Release();
  308.             m_SAN = NULL;
  309.         }
  310.  
  311.         if(m_Gb)
  312.         {
  313.             m_Gb->Release();
  314.             m_Gb = NULL;
  315.         }
  316.  
  317.         if(m_Fg)
  318.         {
  319.             m_Fg->Release();
  320.             m_Fg = NULL;
  321.         }
  322.     }
  323.  
  324.     delete m_lpBltAlpha;
  325.  
  326.     RELEASE(m_lpDDObj);
  327.     RELEASE(m_lpPriSurf);
  328.     RELEASE(m_lpBackBuffer);
  329.     RELEASE(m_lpDDTexture);
  330.     RELEASE(m_lpDDAppImage);
  331.  
  332.     if(m_hFont)
  333.     {
  334.         DeleteObject(m_hFont);
  335.         m_hFont = NULL;
  336.     }
  337.  
  338.     RELEASE(m_lpDDSFontCache);
  339.  
  340.     QzUninitialize();
  341.     return 0L;
  342. }
  343.  
  344.  
  345. /******************************Public*Routine******************************\
  346. * CMpegMovie::GetNativeMovieSize
  347. *
  348. \**************************************************************************/
  349. BOOL
  350. CMpegMovie::GetNativeMovieSize(
  351.     LONG *pcx,
  352.     LONG *pcy
  353.     )
  354. {
  355.     BOOL    bRet = FALSE;
  356.     if(m_Wc)
  357.     {
  358.         bRet = (m_Wc->GetNativeVideoSize(pcx, pcy, NULL, NULL) == S_OK);
  359.     }
  360.  
  361.     return bRet;
  362. }
  363.  
  364.  
  365. /******************************Public*Routine******************************\
  366. * GetMoviePosition
  367. *
  368. \**************************************************************************/
  369. BOOL
  370. CMpegMovie::GetMoviePosition(
  371.     LONG *px,
  372.     LONG *py,
  373.     LONG *pcx,
  374.     LONG *pcy
  375.     )
  376. {
  377.     BOOL    bRet = FALSE;
  378.  
  379.     if(m_Wc)
  380.     {
  381.         RECT src={0}, dest={0};
  382.         HRESULT hr = m_Wc->GetVideoPosition(&src, &dest);
  383.         *px = dest.left;
  384.         *py = dest.right;
  385.         *pcx = dest.right - dest.left;
  386.         *pcy = dest.bottom - dest.top;
  387.     }
  388.     
  389.     return bRet;
  390. }
  391.  
  392. /******************************Public*Routine******************************\
  393. * PutMoviePosition
  394. *
  395. \**************************************************************************/
  396. BOOL
  397. CMpegMovie::PutMoviePosition(
  398.     LONG x,
  399.     LONG y,
  400.     LONG cx,
  401.     LONG cy
  402.     )
  403. {
  404.     BOOL    bRet = TRUE;
  405.  
  406.     RECT rc;
  407.     SetRect(&rc, x, y, x + cx, y + cy);
  408.  
  409.     if(m_bRndLess)
  410.     {
  411.         CAutoLock Lock(&m_AppImageLock);
  412.         MapWindowRect(m_hwndApp, HWND_DESKTOP, &rc);
  413.         m_rcDst = rc;
  414.         CreateFontCache(HEIGHT(&m_rcDst) / GRID_CY);
  415.     }
  416.     else
  417.     {
  418.         if(m_Wc)
  419.         {
  420.             bRet = (m_Wc->SetVideoPosition(NULL, &rc) == S_OK);
  421.         }
  422.     }
  423.  
  424.     return bRet;
  425. }
  426.  
  427.  
  428. /******************************Public*Routine******************************\
  429. * PlayMovie
  430. *
  431. \**************************************************************************/
  432. BOOL
  433. CMpegMovie::PlayMovie(
  434.     )
  435. {
  436.     REFTIME rt;
  437.     REFTIME rtAbs;
  438.     REFTIME rtDur;
  439.  
  440.     rt = GetCurrentPosition();
  441.     rtDur = GetDuration();
  442.  
  443.     //
  444.     // If we are near the end of the movie seek to the start, otherwise
  445.     // stay where we are.
  446.     //
  447.     rtAbs = rt - rtDur;
  448.     if(rtAbs < (REFTIME)0)
  449.     {
  450.         rtAbs = -rtAbs;
  451.     }
  452.  
  453.     if(rtAbs < (REFTIME)1)
  454.     {
  455.         SeekToPosition((REFTIME)0,FALSE);
  456.     }
  457.  
  458.     //
  459.     // Change mode after setting m_Mode but before starting the graph
  460.     //
  461.     m_Mode = MOVIE_PLAYING;
  462.  
  463.     //
  464.     // Start playing from the begining of the movie
  465.     //
  466.     m_Mc->Run();
  467.     return TRUE;
  468. }
  469.  
  470.  
  471. /******************************Public*Routine******************************\
  472. * PauseMovie
  473. *
  474. \**************************************************************************/
  475. BOOL
  476. CMpegMovie::PauseMovie(
  477.     )
  478. {
  479.     m_Mode = MOVIE_PAUSED;
  480.     m_Mc->Pause();
  481.     return TRUE;
  482. }
  483.  
  484.  
  485. /******************************Public*Routine******************************\
  486. * GetStateMovie
  487. *
  488. \**************************************************************************/
  489.  
  490. OAFilterState
  491. CMpegMovie::GetStateMovie(
  492.     )
  493. {
  494.     OAFilterState State;
  495.     m_Mc->GetState(INFINITE,&State);
  496.     return State;
  497. }
  498.  
  499.  
  500. /******************************Public*Routine******************************\
  501. * StopMovie
  502. *
  503. \**************************************************************************/
  504. BOOL
  505. CMpegMovie::StopMovie(
  506.     )
  507. {
  508.     m_Mode = MOVIE_STOPPED;
  509.     m_Mc->Stop();
  510.     return TRUE;
  511. }
  512.  
  513.  
  514. /******************************Public*Routine******************************\
  515. * StatusMovie
  516. *
  517. \**************************************************************************/
  518. EMpegMovieMode
  519. CMpegMovie::StatusMovie(
  520.     )
  521. {
  522.     if(m_Mc)
  523.     {
  524.         FILTER_STATE    fs;
  525.         HRESULT         hr;
  526.  
  527.         hr = m_Mc->GetState(100, (OAFilterState *)&fs);
  528.  
  529.         // Don't know what the state is so just stay at old state.
  530.         if(hr == VFW_S_STATE_INTERMEDIATE)
  531.         {
  532.             return m_Mode;
  533.         }
  534.  
  535.         switch(fs)
  536.         {
  537.             case State_Stopped:
  538.                 m_Mode = MOVIE_STOPPED;
  539.                 break;
  540.  
  541.             case State_Paused:
  542.                 m_Mode = MOVIE_PAUSED;
  543.                 break;
  544.  
  545.             case State_Running:
  546.                 m_Mode = MOVIE_PLAYING;
  547.                 break;
  548.         }
  549.     }
  550.  
  551.     return m_Mode;
  552. }
  553.  
  554.  
  555. /******************************Public*Routine******************************\
  556. * CanMovieFrameStep
  557. *
  558. \**************************************************************************/
  559. BOOL
  560. CMpegMovie::CanMovieFrameStep()
  561. {
  562.     IVideoFrameStep* lpFS;
  563.     HRESULT hr;
  564.  
  565.     hr = m_Fg->QueryInterface(__uuidof(IVideoFrameStep), (LPVOID *)&lpFS);
  566.     if(SUCCEEDED(hr))
  567.     {
  568.         hr = lpFS->CanStep(0L, NULL);
  569.         lpFS->Release();
  570.     }
  571.  
  572.     return SUCCEEDED(hr);
  573. }
  574.  
  575.  
  576. /******************************Public*Routine******************************\
  577. * FrameStepMovie
  578. *
  579. \**************************************************************************/
  580. BOOL
  581. CMpegMovie::FrameStepMovie()
  582. {
  583.     IVideoFrameStep* lpFS;
  584.     HRESULT hr;
  585.  
  586.     hr = m_Fg->QueryInterface(__uuidof(IVideoFrameStep), (LPVOID *)&lpFS);
  587.     if(SUCCEEDED(hr))
  588.     {
  589.         FrameStepCount++;
  590.  
  591.         hr = lpFS->Step(1, NULL);
  592.         lpFS->Release();
  593.     }
  594.  
  595.     return SUCCEEDED(hr);
  596. }
  597.  
  598.  
  599. /******************************Public*Routine******************************\
  600. * GetMediaEventHandle
  601. *
  602. * Returns the IMediaEvent event hamdle for the filter graph iff the
  603. * filter graph exists.
  604. *
  605. \**************************************************************************/
  606. HANDLE
  607. CMpegMovie::GetMovieEventHandle(
  608.     )
  609. {
  610.     HRESULT     hr;
  611.  
  612.     if(m_Me != NULL)
  613.     {
  614.         if(m_MediaEvent == NULL)
  615.         {
  616.             hr = m_Me->GetEventHandle((OAEVENT *)&m_MediaEvent);
  617.         }
  618.     }
  619.     else
  620.     {
  621.         m_MediaEvent = NULL;
  622.     }
  623.  
  624.     return m_MediaEvent;
  625. }
  626.  
  627.  
  628. /******************************Public*Routine******************************\
  629. * GetMovieEventCode
  630. *
  631. \**************************************************************************/
  632. long
  633. CMpegMovie::GetMovieEventCode()
  634. {
  635.     HRESULT hr;
  636.     long    lEventCode;
  637.     LONG_PTR    lParam1, lParam2;
  638.  
  639.     if(m_Me != NULL)
  640.     {
  641.         hr = m_Me->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
  642.         if(SUCCEEDED(hr))
  643.         {
  644.             hr = m_Me->FreeEventParams(lEventCode, lParam1, lParam2);
  645.             return lEventCode;
  646.         }
  647.     }
  648.  
  649.     return 0L;
  650. }
  651.  
  652.  
  653. /******************************Public*Routine******************************\
  654. * GetDuration
  655. *
  656. * Returns the duration of the current movie
  657. *
  658. \**************************************************************************/
  659. REFTIME
  660. CMpegMovie::GetDuration()
  661. {
  662.     HRESULT hr;
  663.     LONGLONG Duration;
  664.  
  665.     if(m_TimeFormat != TIME_FORMAT_MEDIA_TIME)
  666.     {
  667.         hr = m_Ms->GetDuration(&Duration);
  668.         if(SUCCEEDED(hr))
  669.         {
  670.             return double(Duration);
  671.         }
  672.     }
  673.     else if(m_Ms != NULL)
  674.     {
  675.         hr = m_Ms->GetDuration(&Duration);
  676.         if(SUCCEEDED(hr))
  677.         {
  678.             return double(Duration) / UNITS;
  679.         }
  680.     }
  681.     return 0;
  682. }
  683.  
  684.  
  685. /******************************Public*Routine******************************\
  686. * GetCurrentPosition
  687. *
  688. * Returns the duration of the current movie
  689. *
  690. \**************************************************************************/
  691. REFTIME
  692. CMpegMovie::GetCurrentPosition()
  693. {
  694.     REFTIME rt = (REFTIME)0;
  695.     HRESULT hr;
  696.     LONGLONG Position;
  697.  
  698.     // Should we return a media position
  699.  
  700.     if(m_TimeFormat != TIME_FORMAT_MEDIA_TIME)
  701.     {
  702.         hr = m_Ms->GetPositions(&Position, NULL);
  703.         if(SUCCEEDED(hr))
  704.         {
  705.             return double(Position);
  706.         }
  707.     }
  708.     else if(m_Ms != NULL)
  709.     {
  710.         hr = m_Ms->GetPositions(&Position, NULL);
  711.         if(SUCCEEDED(hr))
  712.         {
  713.             return double(Position) / UNITS;
  714.         }
  715.     }
  716.     return rt;
  717. }
  718.  
  719.  
  720. /*****************************Private*Routine******************************\
  721. * SeekToPosition
  722. *
  723. \**************************************************************************/
  724. BOOL
  725. CMpegMovie::SeekToPosition(
  726.     REFTIME rt,
  727.     BOOL bFlushData
  728.     )
  729. {
  730.     HRESULT hr=S_OK;
  731.     LONGLONG llTime = LONGLONG(m_TimeFormat == TIME_FORMAT_MEDIA_TIME ? rt * double(UNITS) : rt );
  732.  
  733.     if(m_Ms != NULL)
  734.     {
  735.         FILTER_STATE fs;
  736.         m_Mc->GetState(100, (OAFilterState *)&fs);
  737.  
  738.         hr = m_Ms->SetPositions(&llTime, AM_SEEKING_AbsolutePositioning, NULL, 0);
  739.  
  740.         // This gets new data through to the renderers
  741.         if(fs == State_Stopped && bFlushData)
  742.         {
  743.             m_Mc->Pause();
  744.             hr = m_Mc->GetState(INFINITE, (OAFilterState *)&fs);
  745.             m_Mc->Stop();
  746.         }
  747.  
  748.         if(SUCCEEDED(hr))
  749.         {
  750.             return TRUE;
  751.         }
  752.     }
  753.     return FALSE;
  754. }
  755.  
  756.  
  757. /*****************************Private*Routine******************************\
  758. * GetPerformanceInterfaces
  759. *
  760. \**************************************************************************/
  761. void
  762. CMpegMovie::GetPerformanceInterfaces(
  763.     )
  764. {
  765.     FindInterfaceFromFilterGraph(IID_IMpegAudioDecoder, (LPVOID *)&pMpegAudioDecoder);
  766.     FindInterfaceFromFilterGraph(IID_IQualProp, (LPVOID *)&pVideoRenderer);
  767. }
  768.  
  769.  
  770. HRESULT
  771. CMpegMovie::FindInterfaceFromFilterGraph(
  772.     REFIID iid, // interface to look for
  773.     LPVOID *lp  // place to return interface pointer in
  774.     )
  775. {
  776.     IEnumFilters*   pEF;    
  777.     IBaseFilter*        pFilter;
  778.  
  779.     // Grab an enumerator for the filter graph.
  780.     HRESULT hr = m_Fg->EnumFilters(&pEF);
  781.  
  782.     if(FAILED(hr))
  783.     {
  784.         return hr;
  785.     }
  786.  
  787.     // Check out each filter.
  788.     while(pEF->Next(1, &pFilter, NULL) == S_OK)
  789.     {
  790.         hr = pFilter->QueryInterface(iid, lp);
  791.         pFilter->Release();
  792.  
  793.         if(SUCCEEDED(hr))
  794.         {
  795.             break;
  796.         }
  797.     }
  798.  
  799.     pEF->Release();
  800.  
  801.     return hr;
  802. }
  803.  
  804.  
  805. /*****************************Public*Routine******************************\
  806. * IsTimeFormatSupported
  807. *
  808. \**************************************************************************/
  809. BOOL
  810. CMpegMovie::IsTimeFormatSupported(GUID Format)
  811. {
  812.     return m_Ms != NULL && m_Ms->IsFormatSupported(&Format) == S_OK;
  813. }
  814.  
  815.  
  816. /*****************************Public*Routine******************************\
  817. * IsTimeSupported
  818. *
  819. \**************************************************************************/
  820. BOOL
  821. CMpegMovie::IsTimeSupported()
  822. {
  823.     return m_Ms != NULL && m_Ms->IsFormatSupported(&TIME_FORMAT_MEDIA_TIME) == S_OK;
  824. }
  825.  
  826.  
  827. /*****************************Public*Routine******************************\
  828. * GetTimeFormat
  829. *
  830. \**************************************************************************/
  831. GUID
  832. CMpegMovie::GetTimeFormat()
  833. {
  834.     return m_TimeFormat;
  835. }
  836.  
  837. /*****************************Public*Routine******************************\
  838. * SetTimeFormat
  839. *
  840. \**************************************************************************/
  841. BOOL
  842. CMpegMovie::SetTimeFormat(GUID Format)
  843. {
  844.     HRESULT hr = m_Ms->SetTimeFormat(&Format);
  845.     if(SUCCEEDED(hr))
  846.     {
  847.         m_TimeFormat = Format;
  848.     }
  849.     return SUCCEEDED(hr);
  850. }
  851.  
  852. /******************************Public*Routine******************************\
  853. * SetFocus
  854. *
  855. \**************************************************************************/
  856. void
  857. CMpegMovie::SetFocus()
  858. {
  859.     if(m_Fg)
  860.     {
  861.         // Tell the resource manager that we are being made active.  This
  862.         // will then cause the sound to switch to us.  This is especially
  863.         // important when playing audio only files as there is no other
  864.         // playback window.
  865.         IResourceManager* pResourceManager;
  866.  
  867.         HRESULT hr = m_Fg->QueryInterface(IID_IResourceManager, (void**)&pResourceManager);
  868.  
  869.         if(SUCCEEDED(hr))
  870.         {
  871.             IUnknown* pUnknown;
  872.  
  873.             hr = m_Fg->QueryInterface(IID_IUnknown, (void**)&pUnknown);
  874.  
  875.             if(SUCCEEDED(hr))
  876.             {
  877.                 pResourceManager->SetFocus(pUnknown);
  878.                 pUnknown->Release();
  879.             }
  880.  
  881.             pResourceManager->Release();
  882.         }
  883.     }
  884. }
  885.  
  886.  
  887. /******************************Public*Routine******************************\
  888. * RepaintVideo
  889. *
  890. \**************************************************************************/
  891. BOOL
  892. CMpegMovie::RepaintVideo(
  893.     HWND hwnd,
  894.     HDC hdc
  895.     )
  896. {
  897.     BOOL bRet = FALSE;
  898.  
  899.     if(m_Wc)
  900.     {
  901.         bRet = (m_Wc->RepaintVideo(hwnd, hdc) == S_OK);
  902.     }
  903.  
  904.     return bRet;
  905. }
  906.  
  907.  
  908. /******************************Public*Routine******************************\
  909. * VerifyVMR
  910. *
  911. \**************************************************************************/
  912. BOOL VerifyVMR(void)
  913. {
  914.     HRESULT hres;
  915.  
  916.     // Verify that the VMR exists on this system
  917.     IBaseFilter* pBF = NULL;
  918.     hres = CoCreateInstance(CLSID_VideoMixingRenderer,
  919.         NULL,
  920.         CLSCTX_INPROC,
  921.         IID_IBaseFilter,
  922.         (LPVOID *)&pBF);
  923.  
  924.     if(SUCCEEDED(hres))
  925.     {
  926.         pBF->Release();
  927.         return TRUE;
  928.     }
  929.     else
  930.     {
  931.         MessageBox(hwndApp, 
  932.             TEXT("This application requires the Video Mixing Renderer, which is present\r\n")
  933.             TEXT("only on Windows XP.\r\n\r\n")
  934.             TEXT("The Video Mixing Renderer (VMR) is also not enabled when viewing a \r\n")
  935.             TEXT("remote Windows XP machine through a Remote Desktop session.\r\n")
  936.             TEXT("You can run VMR-enabled applications only on your local machine.")
  937.             TEXT("\r\n\r\nThis sample will now exit."),
  938.             TEXT("Video Mixing Renderer capabilities are required"), MB_OK);
  939.  
  940.         return FALSE;
  941.     }
  942. }
  943.  
  944.  
  945.